using System.Data;
using System.Text.Json;
using GEM.Application.Common;
using GEM.Application.Dto;
using GEM.Application.Dto.User;
using GEM.Application.Repositories;
using GEM.Domain.Entities.App;
using GEM.Domain.Repositories;

namespace GEM.Application.Services;

public class UserService : IUserService
{
    private readonly IDapperRepository<AppUser> _IDappperRep;
    private readonly IDapperRepository<AppRole> _roleRep;
    private readonly IRepository<AppUser> _efUserRep;
    private readonly IRepository<AppRole> _efRoleRep;
    public UserService(IRepository<AppRole> efRoleRep, IDapperRepository<AppUser> IDappperRep, IDapperRepository<AppRole> roleRep, IRepository<AppUser> efUserRep)
    {
        _IDappperRep = IDappperRep;
        _roleRep = roleRep;
        _efUserRep = efUserRep;
        _efRoleRep = efRoleRep;
    }

    // 根据id获取用户基本信息
    public async Task<dynamic> GetByIdAsync(Guid id)
    {
        var user = await _efUserRep.GetByIdWithIncludesAsync(
        id,
        u => u.Roles
    );
        if (user == null)
        {
            return ApiResponse<string>.Fail(4001, "用户不存在，请确认后重试!!");
        }
        var userDto = new UserDto(
            user.Id,
            user.Username,
            user.Email,
            user.AvatarUrl,
            user.Phone,
            user.Nickname,
            user.Roles.Select(r => r.RoleName),
            user.IsActived,
            user.IsDeleted,
            user.CreatedAt,
            user.UpdatedAt,
            user.Remarks
        );
        return ApiResponse<UserDto>.Success(userDto);
    }

    //获取所有用户
    // public async Task<IEnumerable<UserDto>> GetUserListAsync()
    // {
    //     var users = await _IDappperRep.GetAllAsync();
    //     return users.Select(userDto => new UserDto
    //     {
    //         Id = userDto.Id,
    //         Username = userDto.Username,
    //         Email = userDto.Email,
    //         Phone = userDto.Phone,
    //         IsActived = userDto.IsActived,
    //         IsDeleted = userDto.IsDeleted,
    //         UpdatedAt = DateTime.UtcNow,
    //         Remarks = userDto.Remarks
    //         // 其他属性映射...
    //     }).ToList();
    // }

    //更新用户
    public async Task<int> UserUpdateAsync(Guid id, UserDto userDto)
    {

        var user = await _IDappperRep.GetByIdAsync(id);
        if (user == null)
        {
            return 0;
        }
        user.Username = userDto.Username;
        user.Email = userDto.Email;
        user.Phone = userDto.Phone;
        user.IsActived = userDto.IsActived;
        user.IsDeleted = userDto.IsDeleted;
        user.UpdatedAt = DateTime.UtcNow;
        user.Remarks = userDto.Remarks;

        await _IDappperRep.UpdateAsync(user);
        return 1;

    }

    //软删除
    public async Task<dynamic> DeletedByIdAsync(Guid id)
    {
        var user = await _IDappperRep.GetByIdAsync(id);
        if (user == null)
        {
            return ApiResponse<string>.Fail(1004, "用户不存在,请确认后重试!!");
        }
        if (user.IsDeleted == true)
        {
            return ApiResponse<string>.Fail(1004, "该用户已删除,请确认后重试!!");
        }
        user.IsDeleted = true;
        await _IDappperRep.UpdateAsync(user);
        return ApiResponse<string>.Success("删除成功");
    }

    //真删除 未使用
    public async Task<dynamic> DeleteByIdAsync(Guid id)
    {
        var user = await _IDappperRep.GetByIdAsync(id);
        if (user == null)
        {
            return ApiResponse<string>.Fail(1004, "用户不存在,请确认后重试!!");
        }
        await _efUserRep.DeleteAsync(user);
        return ApiResponse<string>.Success("删除成功");
    }

    //启用用户
    public async Task<dynamic> EnableUserAsync(Guid id)
    {
        var user = await _IDappperRep.GetByIdAsync(id);
        if (user == null)
        {
            return ApiResponse<string>.Fail(1004, "用户不存在,请确认后重试!!");
        }
        if (user.IsDeleted == true)
        {
            return ApiResponse<string>.Fail(1004, "该用户已删除,请确认后重试!!");
        }
        if (user.IsActived == true)
        {
            return ApiResponse<string>.Fail(1004, "用户已启用,无需重复启用");
        }
        user.IsActived = true;
        var number = await _IDappperRep.UpdateAsync(user);
        if (number > 0)
        {
            return ApiResponse<string>.Success("启用成功");
        }
        return ApiResponse<string>.Fail(1004, "启用失败,请重试!!");
    }

    //禁用用户
    public async Task<dynamic> DisableUserAsync(Guid id)
    {
        var user = await _IDappperRep.GetByIdAsync(id);
        if (user == null)
        {
            return ApiResponse<string>.Fail(1004, "用户不存在,请确认后重试!!");
        }
        if (user.IsDeleted == true)
        {
            return ApiResponse<string>.Fail(1004, "该用户已删除,请确认后重试!!");
        }
        if (user.IsActived == false)
        {
            return ApiResponse<string>.Fail(1004, "用户已禁用,无需重复禁用");
        }
        user.IsActived = false;
        var number = await _IDappperRep.UpdateAsync(user);
        if (number > 0)
        {
            return ApiResponse<string>.Success("禁用成功");
        }
        return ApiResponse<string>.Fail(1004, "禁用失败,请重试!!");
    }

    //修改密码
    public async Task<dynamic> ChangePasswordAsync(Guid id, string oldPwd, string newPwd)
    {
        var user = await _IDappperRep.GetByIdAsync(id) ?? throw new Exception("用户不存在!!");
        if (HashPassword(oldPwd, user.Salt) != user.Password)
        {
            return ApiResponse<string>.Fail(1004, "原密码错误,请确认后重试!!");
        }
        if (HashPassword(newPwd, user.Salt) == user.Password)
        {
            return ApiResponse<string>.Fail(1004, "新密码与旧密码相同,请使用不同的代码!!");
        }
        user.Password = HashPassword(newPwd, user.Salt);
        var number = await _IDappperRep.UpdateAsync(user);
        if (number > 0)
        {
            return ApiResponse<string>.Success("修改密码成功!");
        }
        return ApiResponse<string>.Fail(1004, "修改失败，请重试!!");
    }

    //简单的密码哈希函数，实际应用中请使用更安全的哈希算法和盐值
    private string HashPassword(string password, string salt)
    {
        using var sha256 = System.Security.Cryptography.SHA256.Create();
        var bytes = System.Text.Encoding.UTF8.GetBytes(password + salt);
        var hash = sha256.ComputeHash(bytes);
        return Convert.ToBase64String(hash);
    }

    /// <summary>
    /// 分配角色
    /// </summary>
    /// <param name="uId"></param>
    /// <param name="rId"></param>
    /// <returns></returns>
    public async Task<dynamic> AssignRoleAsync(Guid userId, Guid roleId)
    {
        var user = await _IDappperRep.GetByIdAsync(userId);
        if (user == null)
        {
            return ApiResponse<string>.Fail(4001, "用户不存在，请确认后重试!!");
        }
        var role = await _roleRep.GetByIdAsync(roleId);
        if (role == null)
        {
            return ApiResponse<string>.Fail(4002, "角色不存在,请确认后重试!!");
        }
        var isTrue = user.AssignRole(role);
        if (isTrue)
        {
            await _efUserRep.UpdateAsync(user);
            return ApiResponse<string>.Success($"为{user.Username}分配{role.RoleName}角色成功");
        }
        return ApiResponse<string>.Fail(4003, "操作失败，请重试!!");
    }

    /// <summary>
    /// 移除角色
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="roleId"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public async Task<dynamic> RemoveRoleAsync(Guid userId, Guid roleId)
    {
        var user = await _efUserRep.GetUserWithRolesAsync(userId);
        // var user = await _IDappperRep.GetByIdAsync(userId);   不包含导航属性
        // var user = await _IDappperRep.GetByIdAsync(userId);   不包含导航属性
        if (user == null)
        {
            return ApiResponse<string>.Fail(4001, "用户不存在，请确认后重试!!");
        }
        var role = await _efRoleRep.GetByIdAsync(roleId);
        // var role = user.Roles.FirstOrDefault(r => r.Id == roleId);
        if (role == null)
        {
            return ApiResponse<string>.Fail(4002, "角色不存在，请确认后重试");
        }
        var isTrue = user.RemoveRole(role);
        if (isTrue)
        {
            await _efUserRep.UpdateAsync(user);
            return ApiResponse<string>.Success($"为{user.Username}移除{role.RoleName}角色成功");
        }
        return ApiResponse<string>.Fail(4003, "操作失败，请重试!!");
    }

    //为指定用户修改昵称
    public async Task<dynamic> ChangeNicknameAsync(Guid userId, string nickname)
    {
        var user = await _IDappperRep.GetByIdAsync(userId);
        if (user == null)
        {
            return ApiResponse<string>.Fail(4001, "用户不存在，请确认后重试!!");
        }
        if (string.IsNullOrWhiteSpace(nickname))
        {
            return ApiResponse<string>.Fail(4002, "昵称不能为空，请确认后重试!!");
        }
        if (user.Nickname == nickname)
        {
            return ApiResponse<string>.Fail(4003, "新昵称与旧昵称一样，请确认后重试!!");

        }
        user.Nickname = nickname;
        var number = await _IDappperRep.UpdateAsync(user);
        if (number > 0)
        {
            return ApiResponse<string>.Success("修改昵称成功");
        }
        return ApiResponse<string>.Fail(4003, "修改昵称失败，请重试!!");
    }

    //为指定用户修改头像
    public async Task<dynamic> ChangeAvatarUrlAsync(Guid userId, string avartarUrl)
    {
        var user = await _IDappperRep.GetByIdAsync(userId);
        if (user == null)
        {
            return ApiResponse<string>.Fail(4001, "用户不存在，请确认后重试!!");
        }
        if (string.IsNullOrWhiteSpace(avartarUrl))
        {
            return ApiResponse<string>.Fail(4002, "头像URL不能为空，请确认后重试!!");
        }
        if (user.AvatarUrl == avartarUrl)
        {
            return ApiResponse<string>.Fail(4003, "新头像URL与旧头像URL一样，请确认后重试!!");
        }
        user.AvatarUrl = avartarUrl;
        var number = await _IDappperRep.UpdateAsync(user);
        if (number > 0)
        {
            return ApiResponse<string>.Success("修改头像成功");
        }
        return ApiResponse<string>.Fail(4004, "修改头像失败，请重试!!");
    }

    //为指定用户修改邮箱
    public async Task<dynamic> ChangeEmailAsync(Guid userId, string email)
    {
        var user = await _IDappperRep.GetByIdAsync(userId);
        if (user == null)
        {
            return ApiResponse<string>.Fail(4001, "用户不存在，请确认后重试!!");
        }
        if (string.IsNullOrWhiteSpace(email))
        {
            return ApiResponse<string>.Fail(4002, "邮箱不能为空，请确认后重试!!");
        }
        if (user.Email == email)
        {
            return ApiResponse<string>.Fail(4003, "新邮箱与旧邮箱一样，请确认后重试!!");
        }
        user.Email = email;
        var number = await _IDappperRep.UpdateAsync(user);
        if (number > 0)
        {
            return ApiResponse<string>.Success("修改邮箱成功");
        }
        return ApiResponse<string>.Fail(4004, "修改邮箱失败，请重试!!");
    }

    //修改指定用户的所有基本信息
    public async Task<dynamic> ChangeUserAsync(Guid userId, ChangeUserDto changeUserDto)
    {
        var user = await _efUserRep.GetByIdAsync(userId);
        if (user == null)
        {
            return ApiResponse<string>.Fail(4001, "用户不存在，请确认后重试!!");
        }
        user.Nickname = changeUserDto.Nickname;
        user.AvatarUrl = changeUserDto.AvatarUrl;
        user.Email = changeUserDto.Email;
        user.Phone = changeUserDto.Phone;
        user.IsActived = changeUserDto.IsActive;
        await _efUserRep.UpdateAsync(user);
        return ApiResponse<string>.Success("用户信息修改成功");
    }

    /// <summary>
    /// 分页查询用户
    /// </summary>
    /// <param name="pageIndex">页码</param>
    /// <param name="pageSize">每页条数</param>
    /// <returns>分页数据</returns>
    public async Task<PagedResult<UserDto>> GetUserPagedAsync(int pageIndex, int pageSize)
    {
        // 传递导航属性
        var (users, totalCount) = await _efUserRep.GetPagedAsync(
            pageIndex, pageSize, u => u.Roles
        );

        var userDtos = users.Select(user => new UserDto(
            user.Id,
            user.Username,
            user.Email,
            user.AvatarUrl,
            user.Phone,
            user.Nickname,
            user.Roles?.Select(r => r.RoleName) ?? Enumerable.Empty<string>(), // 防止空引用
            user.IsActived,
            user.IsDeleted,
            user.CreatedAt,
            user.UpdatedAt,
            user.Remarks
        )).ToList();

        var totalPage = (int)Math.Ceiling(totalCount / (double)pageSize);

        var pagedResult = new PagedResult<UserDto>
        {
            TotalCount = totalCount,
            TotalPage = totalPage,
            PageIndex = pageIndex,
            PageSize = pageSize,
            Items = userDtos
        };
        return pagedResult;
    }


}